/*
	Copyright (c) 2010 <copyright holders>
	This source code is licensed under The MIT License,
	see the file LICENSE for details.
	*/

#ifndef NETVARS_HPP
#define NETVARS_HPP

#include <boost/shared_ptr.hpp>
#include <map>
#include <string>

#include "ForwardDecls.hpp"
#include "HelpDefs.hpp"
#include "NetDefs.hpp"
#include <exception>

namespace spelprog2 {
namespace net {

/**
    Represents server values that should (mostly) be mirrored automatically to clients.
    However, Server/Client/Local classes handle message reception.
    */
class NetVars {
public:
    typedef std::map<std::string, std::string> Vars;
private:
    typedef Vars User;
    typedef boost::shared_ptr<User> UserPtr;
    typedef std::map<UserId, UserPtr> UserMap;

    HIDE_EVIL_CONSTRUCTORS(NetVars);

    UserMap users;
    std::string nullstr;
    UserId nextId;
    Net * net_; //can't be passed as ref through constructor because Net depends on this class
    bool isServer_;
public:
    typedef Vars::const_iterator VarsConstIterator;

    explicit NetVars(bool isServer);
    ~NetVars();

    void setNetwork(Net * net) { net_ = net; }

    //! Adds a user for server. Don't call for client.
    UserId addUser();

    //! Adds a user for client. Don't call for server.
    void addUser(UserId id);

    //! Removes a user. For the server this also causes a ChangeUser message to be sent.
    void removeUser(UserId id);

    //! Sends entire state to a certain user (must be server).
    void refreshToUser(UserId id);
    
    //this does an "intelligent" update, making the necessary network transfer to change a var
    void setVar(UserId user, const std::string & key, const std::string & val);

    //use this method with care; it is a dumb var change which isn't transferred across network
    bool updateVar(UserId user, const std::string & key, const std::string & val);

    //methods to iterate known variables
    const std::string & getVar(UserId id, const std::string & key) const;
    VarsConstIterator getVars(UserId id) const;

    //! Sees is a certain user exists.
    bool hasUser(UserId id) const { return users.find(id) != users.end(); }

    //! Returns the number of users excluding the server.
    unsigned countClientUsers() const { return users.size() - 1; }

    //! Writes all vars and their values to log.
    void dump();
};

}; //namespace net
}; //namespace spelprog2

#endif //NETVARS_HPP
